import re
from datetime import datetime
from flask import Blueprint, request, current_app
from models.models import User, db
from utils.helpers import api_response, process_image
from services.auth_service import send_verification_code, verify_code

auth_bp = Blueprint('auth', __name__)

@auth_bp.route('/verify-email', methods=['POST'])
def verify_email():
    """
    发送邮箱验证码
    ---
    tags:
      - 认证
    parameters:
      - name: body
        in: body
        required: true
        schema:
          type: object
          required:
            - email
            - purpose
          properties:
            email:
              type: string
              description: 用户邮箱
            purpose:
              type: string
              description: 验证码用途(目前仅支持register)
              enum: [register]
    responses:
      200:
        description: 验证码发送成功
        schema:
          type: object
          properties:
            code:
              type: integer
              example: 200
            message:
              type: string
              example: "验证码已发送至您的邮箱，有效期5分钟"
            data:
              type: object
              properties:
                expire_time:
                  type: integer
                  description: 验证码有效期(秒)
                  example: 300
      400:
        description: 参数错误
      500:
        description: 服务器内部错误
    """
    try:
        data = request.json
        if not data or not data.get('email') or not data.get('purpose'):
            return api_response(message="请求参数不完整，需要email和purpose字段", code=400, status_code=400)
            
        email = data['email']
        purpose = data['purpose']
        
        if purpose != "register":
            return api_response(message="purpose字段值无效，目前仅支持register", code=400, status_code=400)
            
        email_pattern = re.compile(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')
        if not email_pattern.match(email):
            return api_response(message="邮箱格式不正确", code=400, status_code=400)
            
        try:
            code, expiry = send_verification_code(current_app.email_service, current_app.code_manager, 
                                               email, purpose, expire_minutes=5)
            expire_seconds = 300  # 5分钟
        except Exception as e:
            current_app.logger.error(f"发送验证码邮件失败: {str(e)}")
            return api_response(message="发送验证码邮件失败，请稍后重试", code=500, status_code=500)
            
        return api_response(
            data={"expire_time": expire_seconds},
            message="验证码已发送至您的邮箱，有效期5分钟",
            code=200
        )
    except Exception as e:
        current_app.logger.error(f"验证码发送异常: {str(e)}")
        return api_response(message="服务器内部错误", code=500, status_code=500)

@auth_bp.route('/register', methods=['POST'])
def register():
    """
    用户注册
    ---
    tags:
      - 认证
    parameters:
      - name: body
        in: body
        required: true
        schema:
          type: object
          required:
            - username
            - password
            - email
            - verification_code
          properties:
            username:
              type: string
              description: 用户名
            password:
              type: string
              description: 密码
            email:
              type: string
              description: 电子邮箱
            verification_code:
              type: string
              description: 验证码
            avatar:
              type: string
              description: 头像图片的Base64编码(可选)
    responses:
      201:
        description: 注册成功
        schema:
          type: object
          properties:
            code:
              type: integer
              example: 201
            message:
              type: string
              example: "注册成功"
      400:
        description: 参数错误或验证码无效
      500:
        description: 服务器内部错误
    """
    data = request.json
    if not data or not data.get('username') or not data.get('password') or not data.get('email'):
        return api_response(message="请提供用户名、密码和邮箱", code=400, status_code=400)
        
    verification_code = data.get('verification_code')
    if not verification_code:
        return api_response(message="请提供验证码", code=400, status_code=400)
        
    # 验证验证码
    is_valid, message = verify_code(current_app.code_manager, data['email'], verification_code, "register")
    if not is_valid:
        return api_response(message=message, code=400, status_code=400)
        
    if User.query.filter_by(username=data['username']).first():
        return api_response(message="用户名已存在", code=400, status_code=400)
        
    if User.query.filter_by(email=data['email']).first():
        return api_response(message="邮箱已被注册", code=400, status_code=400)
        
    new_user = User(
        username=data['username'],
        password_hash=data['password'],
        email=data['email'],
        role='USER'
    )
    
    if data.get('avatar'):
        try:
            avatar_path = process_image(current_app, data['avatar'], 'avatars')
            new_user.avatar_path = avatar_path
        except Exception as e:
            return api_response(message=f"头像处理失败: {str(e)}", code=500, status_code=500)
    
    try:
        db.session.add(new_user)
        db.session.commit()
        return api_response(message="注册成功", code=201, status_code=201)
    except Exception as e:
        db.session.rollback()
        return api_response(message=f"注册失败: {str(e)}", code=500, status_code=500)

@auth_bp.route('/login', methods=['POST'])
def login():
    """
    用户登录
    ---
    tags:
      - 认证
    parameters:
      - name: body
        in: body
        required: true
        schema:
          type: object
          required:
            - username
            - password
          properties:
            username:
              type: string
              description: 用户名
            password:
              type: string
              description: 密码
    responses:
      200:
        description: 登录成功
        schema:
          type: object
          properties:
            code:
              type: integer
              example: 200
            message:
              type: string
              example: "登录成功"
            data:
              type: object
              properties:
                role:
                  type: string
                  description: 用户角色
                  enum: [USER, ADMIN]
                avatar:
                  type: string
                  description: 用户头像完整URL
                user_id:
                  type: integer
                  description: 用户ID
      400:
        description: 参数错误
      401:
        description: 用户名或密码错误
    """
    data = request.json
    if not data or not data.get('username') or not data.get('password'):
        return api_response(message="请提供用户名和密码", code=400, status_code=400)
        
    user = User.query.filter_by(username=data['username']).first()
    if not user or user.password_hash != data['password']:
        return api_response(message="用户名或密码错误", code=401, status_code=401)
        
    user.last_login = datetime.utcnow()
    db.session.commit()
    
    # 处理头像URL，确保可直接访问
    avatar_url = None
    if user.avatar_path:
        # 判断是否已经是完整URL
        if user.avatar_path.startswith(('http://', 'https://')):
            avatar_url = user.avatar_path
        else:
            # 构建完整URL
            base_url = request.host_url.rstrip('/')
            # 移除开头的斜杠，以避免双斜杠
            clean_path = user.avatar_path.lstrip('/')
            avatar_url = f"{base_url}/static/{clean_path}"
    
    return api_response(
        data={
            "user_id": user.user_id,
            "role": user.role,
            "avatar": avatar_url
        },
        message="登录成功",
        code=200
    )

@auth_bp.route('/reset-password', methods=['POST'])
def reset_password():
    """
    重置密码
    ---
    tags:
      - 认证
    parameters:
      - name: body
        in: body
        required: true
        schema:
          type: object
          required:
            - email
          properties:
            email:
              type: string
              description: 用户邮箱
            verification_code:
              type: string
              description: 验证码(第二次请求时需要)
            new_password:
              type: string
              description: 新密码(第二次请求时需要)
    responses:
      200:
        description: 验证码已发送或密码重置成功
        schema:
          type: object
          properties:
            code:
              type: integer
              example: 200
            message:
              type: string
              example: "验证码已发送到您的邮箱"
      400:
        description: 参数错误
      404:
        description: 邮箱未注册
      500:
        description: 服务器内部错误
    """
    data = request.json
    if not data or not data.get('email'):
        return api_response(message="请提供邮箱", code=400, status_code=400)
        
    user = User.query.filter_by(email=data['email']).first()
    if not user:
        return api_response(message="该邮箱未注册", code=404, status_code=404)
        
    if not data.get('verification_code'):
        try:
            send_verification_code(current_app.email_service, current_app.code_manager, 
                                user.email, "reset", expire_minutes=10)
            return api_response(message="验证码已发送到您的邮箱")
        except Exception as e:
            return api_response(message=f"发送邮件失败: {str(e)}", code=500, status_code=500)
            
    if not data.get('new_password'):
        return api_response(message="请提供新密码", code=400, status_code=400)
        
    is_valid, message = verify_code(current_app.code_manager, user.email, data['verification_code'], "reset")
    if not is_valid:
        return api_response(message=message, code=400, status_code=400)
        
    try:
        user.password_hash = data['new_password']
        db.session.commit()
        return api_response(message="密码重置成功", code=200)
    except Exception as e:
        db.session.rollback()
        return api_response(message=f"密码重置失败: {str(e)}", code=500, status_code=500) 